package cn.cdutetc.library.common;

import cn.cdutetc.library.common.exception.BizException;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * Excel工具类
 */
@Slf4j
public class ExcelUtils<T> {
    
    /**
     * 读取Excel文件
     * @param in 读取的文件流
     * @param clazz 与excel文件数据对应的实体
     * @param listener 数据读取解析监听器
     * @return 读取的数据列表
     */
    public static <T> List<T> readExcelFile(InputStream in, Class<T> clazz, com.alibaba.excel.read.listener.ReadListener<T> listener) {
        ExcelReader reader = null;
        try {
            reader = EasyExcel.read(in, clazz, listener).build();
            reader.readAll();
        } catch (Exception e) {
            log.error("读取excel文件错误：" + e.getMessage());
            throw new BizException("读取Excel文件失败: " + e.getMessage());
        } finally {
            // 关闭流,读的时候会创建临时文件，不关闭到时磁盘会崩的
            if (reader != null) {
                reader.finish();
            }
        }
        // 对于新的监听器，我们需要从监听器中获取数据
        if (listener instanceof BookExcelAnalysisEventListener) {
            return (List<T>) ((BookExcelAnalysisEventListener) listener).getCachedDataList();
        } else if (listener instanceof UserExcelAnalysisEventListener) {
            return (List<T>) ((UserExcelAnalysisEventListener) listener).getCachedDataList();
        }
        return new ArrayList<>();
    }

    /**
     * 响应导出Excel
     * @param data 数据列表
     * @param response HTTP响应
     * @param fileName 文件名
     * @param clazz 实体类
     * @return 是否成功
     */
    public static <T> Boolean responseExcelFile(List<T> data, HttpServletResponse response, String fileName, Class<T> clazz) {
        // 设置响应类型
        response.setContentType("application/octet-stream;charset=utf-8");
        // 设置编码格式
        response.setCharacterEncoding("utf-8");
        try {
            // 设置URLEncoder.encode 防止中文乱码
            fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            // 设置响应头
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
            // 把集合对象作为响应流响应给前端浏览器
            EasyExcel.write(response.getOutputStream(), clazz).sheet("模板").doWrite(data);
        } catch (IOException e) {
            log.error("导出Excel文件错误:{}", e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 保存数据到Excel文件
     * @param data 数据列表
     * @param savePath 保存路径
     * @param clazz 实体类
     * @return 是否保存成功
     */
    public static <T> Boolean writeExcelFile(List<T> data, String savePath, Class<T> clazz) {
        if (data == null || savePath == null || clazz == null) {
            log.error("保存Excel参数不能为空");
            return false;
        }
        
        if (data.isEmpty()) {
            log.warn("数据列表为空，跳过保存");
            return false;
        }
        
        try {
            // 确保目录存在
            java.io.File file = new java.io.File(savePath);
            java.io.File parentDir = file.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                if (!parentDir.mkdirs()) {
                    log.error("无法创建目录: {}", parentDir.getAbsolutePath());
                    return false;
                }
            }
            
            // 手动管理ExcelWriter资源
            ExcelWriter excelWriter = null;
            try {
                excelWriter = EasyExcel.write(savePath, clazz).build();
                WriteSheet writeSheet = EasyExcel.writerSheet("数据")
                        .registerWriteHandler(new com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy())
                        .build();
                excelWriter.write(data, writeSheet);
            } finally {
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
            
            log.info("Excel文件保存成功: {}", savePath);
            return true;
        } catch (Exception e) {
            log.error("保存数据到excel错误: {}", e.getMessage(), e);
            return false;
        }
    }
}

